



using System;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using SubSonic.DataProviders;
using SubSonic.Extensions;
using SubSonic.Linq.Structure;
using SubSonic.Query;
using SubSonic.Schema;
using System.Data.Common;
using System.Collections.Generic;

namespace RingCast
{
    public partial class RingCastDB : IQuerySurface
    {

        public IDataProvider DataProvider;
        public DbQueryProvider provider;
        
        public bool TestMode
		{
            get
			{
                return DataProvider.ConnectionString.Equals("test", StringComparison.InvariantCultureIgnoreCase);
            }
        }

        public RingCastDB() 
        { 
            DataProvider = ProviderFactory.GetProvider("RingCast");
            Init();
        }

        public RingCastDB(string connectionStringName)
        {
            DataProvider = ProviderFactory.GetProvider(connectionStringName);
            Init();
        }

		public RingCastDB(string connectionString, string providerName)
        {
            DataProvider = ProviderFactory.GetProvider(connectionString,providerName);
            Init();
        }

		public ITable FindByPrimaryKey(string pkName)
        {
            return DataProvider.Schema.Tables.SingleOrDefault(x => x.PrimaryKey.Name.Equals(pkName, StringComparison.InvariantCultureIgnoreCase));
        }

        public Query<T> GetQuery<T>()
        {
            return new Query<T>(provider);
        }
        
        public ITable FindTable(string tableName)
        {
            return DataProvider.FindTable(tableName);
        }
               
        public IDataProvider Provider
        {
            get { return DataProvider; }
            set {DataProvider=value;}
        }
        
        public DbQueryProvider QueryProvider
        {
            get { return provider; }
        }
        
        BatchQuery _batch = null;
        public void Queue<T>(IQueryable<T> qry)
        {
            if (_batch == null)
                _batch = new BatchQuery(Provider, QueryProvider);
            _batch.Queue(qry);
        }

        public void Queue(ISqlQuery qry)
        {
            if (_batch == null)
                _batch = new BatchQuery(Provider, QueryProvider);
            _batch.Queue(qry);
        }

        public void ExecuteTransaction(IList<DbCommand> commands)
		{
            if(!TestMode)
			{
                using(var connection = commands[0].Connection)
				{
                   if (connection.State == ConnectionState.Closed)
                        connection.Open();
                   
                   using (var trans = connection.BeginTransaction()) 
				   {
                        foreach (var cmd in commands) 
						{
                            cmd.Transaction = trans;
                            cmd.Connection = connection;
                            cmd.ExecuteNonQuery();
                        }
                        trans.Commit();
                    }
                    connection.Close();
                }
            }
        }

        public IDataReader ExecuteBatch()
        {
            if (_batch == null)
                throw new InvalidOperationException("There's nothing in the queue");
            if(!TestMode)
                return _batch.ExecuteReader();
            return null;
        }
			
        public Query<aspnet_User> aspnet_Users { get; set; }
        public Query<Pipe> Pipes { get; set; }
        public Query<MessageAttachment> MessageAttachments { get; set; }
        public Query<GatewayCredential> GatewayCredentials { get; set; }
        public Query<ClientGatewayCredential> ClientGatewayCredentials { get; set; }
        public Query<_RequestLogType> RequestLogTypes { get; set; }
        public Query<RequestLog> RequestLogs { get; set; }
        public Query<Session> Sessions { get; set; }
        public Query<_PlatformSetting> PlatformSettings { get; set; }
        public Query<GatewayIP> GatewayIPs { get; set; }
        public Query<Shell> Shells { get; set; }
        public Query<_MessageType> MessageTypes { get; set; }
        public Query<ShellCredential> ShellCredentials { get; set; }
        public Query<_MessageStatus> MessageStatuses { get; set; }
        public Query<Campaign> Campaigns { get; set; }
        public Query<Gateway> Gateways { get; set; }
        public Query<ClientShellCredential> ClientShellCredentials { get; set; }
        public Query<_MessageDirection> MessageDirections { get; set; }
        public Query<InterfaceResult> InterfaceResults { get; set; }
        public Query<CampaignShell> CampaignShells { get; set; }
        public Query<Message> Messages { get; set; }
        public Query<Country> Countries { get; set; }
        public Query<PipeMapping> PipeMappings { get; set; }
        public Query<OutboundGatewayCountry> OutboundGatewayCountries { get; set; }
        public Query<InboundMessageQueue> InboundMessageQueues { get; set; }
        public Query<NetworkOperator> NetworkOperators { get; set; }
        public Query<OutboundMessageQueue> OutboundMessageQueues { get; set; }
        public Query<Customer> Customers { get; set; }
        public Query<ClientUser> ClientUsers { get; set; }
        public Query<MessageHistory> MessageHistories { get; set; }
        public Query<_ClientStatus> ClientStatuses { get; set; }
        public Query<OutboundBatch> OutboundBatches { get; set; }
        public Query<Client> Clients { get; set; }
        public Query<PipeCampaignKeyword> PipeCampaignKeywords { get; set; }
        public Query<_BillingType> BillingTypes { get; set; }
        public Query<CampaignIdentifierPool> CampaignIdentifierPools { get; set; }
        public Query<OutboundBatchMessage> OutboundBatchMessages { get; set; }

			

        #region ' Aggregates and SubSonic Queries '
        public Select SelectColumns(params string[] columns)
        {
            return new Select(DataProvider, columns);
        }

        public Select Select
        {
            get { return new Select(this.Provider); }
        }

        public Insert Insert
		{
            get { return new Insert(this.Provider); }
        }

        public Update<T> Update<T>() where T:new()
		{
            return new Update<T>(this.Provider);
        }

        public SqlQuery Delete<T>(Expression<Func<T,bool>> column) where T:new()
        {
            LambdaExpression lamda = column;
            SqlQuery result = new Delete<T>(this.Provider);
            result = result.From<T>();
            result.Constraints=lamda.ParseConstraints().ToList();
            return result;
        }

        public SqlQuery Max<T>(Expression<Func<T,object>> column)
        {
            LambdaExpression lamda = column;
            string colName = lamda.ParseObjectValue();
            string objectName = typeof(T).Name;
            string tableName = DataProvider.FindTable(objectName).Name;
            return new Select(DataProvider, new Aggregate(colName, AggregateFunction.Max)).From(tableName);
        }

        public SqlQuery Min<T>(Expression<Func<T,object>> column)
        {
            LambdaExpression lamda = column;
            string colName = lamda.ParseObjectValue();
            string objectName = typeof(T).Name;
            string tableName = this.Provider.FindTable(objectName).Name;
            return new Select(this.Provider, new Aggregate(colName, AggregateFunction.Min)).From(tableName);
        }

        public SqlQuery Sum<T>(Expression<Func<T,object>> column)
        {
            LambdaExpression lamda = column;
            string colName = lamda.ParseObjectValue();
            string objectName = typeof(T).Name;
            string tableName = this.Provider.FindTable(objectName).Name;
            return new Select(this.Provider, new Aggregate(colName, AggregateFunction.Sum)).From(tableName);
        }

        public SqlQuery Avg<T>(Expression<Func<T,object>> column)
        {
            LambdaExpression lamda = column;
            string colName = lamda.ParseObjectValue();
            string objectName = typeof(T).Name;
            string tableName = this.Provider.FindTable(objectName).Name;
            return new Select(this.Provider, new Aggregate(colName, AggregateFunction.Avg)).From(tableName);
        }

        public SqlQuery Count<T>(Expression<Func<T,object>> column)
        {
            LambdaExpression lamda = column;
            string colName = lamda.ParseObjectValue();
            string objectName = typeof(T).Name;
            string tableName = this.Provider.FindTable(objectName).Name;
            return new Select(this.Provider, new Aggregate(colName, AggregateFunction.Count)).From(tableName);
        }

        public SqlQuery Variance<T>(Expression<Func<T,object>> column)
        {
            LambdaExpression lamda = column;
            string colName = lamda.ParseObjectValue();
            string objectName = typeof(T).Name;
            string tableName = this.Provider.FindTable(objectName).Name;
            return new Select(this.Provider, new Aggregate(colName, AggregateFunction.Var)).From(tableName);
        }

        public SqlQuery StandardDeviation<T>(Expression<Func<T,object>> column)
        {
            LambdaExpression lamda = column;
            string colName = lamda.ParseObjectValue();
            string objectName = typeof(T).Name;
            string tableName = this.Provider.FindTable(objectName).Name;
            return new Select(this.Provider, new Aggregate(colName, AggregateFunction.StDev)).From(tableName);
        }

        #endregion

        void Init()
        {
            provider = new DbQueryProvider(this.Provider);

            #region ' Query Defs '
            aspnet_Users = new Query<aspnet_User>(provider);
            Pipes = new Query<Pipe>(provider);
            MessageAttachments = new Query<MessageAttachment>(provider);
            GatewayCredentials = new Query<GatewayCredential>(provider);
            ClientGatewayCredentials = new Query<ClientGatewayCredential>(provider);
            RequestLogTypes = new Query<_RequestLogType>(provider);
            RequestLogs = new Query<RequestLog>(provider);
            Sessions = new Query<Session>(provider);
            PlatformSettings = new Query<_PlatformSetting>(provider);
            GatewayIPs = new Query<GatewayIP>(provider);
            Shells = new Query<Shell>(provider);
            MessageTypes = new Query<_MessageType>(provider);
            ShellCredentials = new Query<ShellCredential>(provider);
            MessageStatuses = new Query<_MessageStatus>(provider);
            Campaigns = new Query<Campaign>(provider);
            Gateways = new Query<Gateway>(provider);
            ClientShellCredentials = new Query<ClientShellCredential>(provider);
            MessageDirections = new Query<_MessageDirection>(provider);
            InterfaceResults = new Query<InterfaceResult>(provider);
            CampaignShells = new Query<CampaignShell>(provider);
            Messages = new Query<Message>(provider);
            Countries = new Query<Country>(provider);
            PipeMappings = new Query<PipeMapping>(provider);
            OutboundGatewayCountries = new Query<OutboundGatewayCountry>(provider);
            InboundMessageQueues = new Query<InboundMessageQueue>(provider);
            NetworkOperators = new Query<NetworkOperator>(provider);
            OutboundMessageQueues = new Query<OutboundMessageQueue>(provider);
            Customers = new Query<Customer>(provider);
            ClientUsers = new Query<ClientUser>(provider);
            MessageHistories = new Query<MessageHistory>(provider);
            ClientStatuses = new Query<_ClientStatus>(provider);
            OutboundBatches = new Query<OutboundBatch>(provider);
            Clients = new Query<Client>(provider);
            PipeCampaignKeywords = new Query<PipeCampaignKeyword>(provider);
            BillingTypes = new Query<_BillingType>(provider);
            CampaignIdentifierPools = new Query<CampaignIdentifierPool>(provider);
            OutboundBatchMessages = new Query<OutboundBatchMessage>(provider);
            #endregion


            #region ' Schemas '
        	if(DataProvider.Schema.Tables.Count == 0)
			{
            	DataProvider.Schema.Tables.Add(new aspnet_UsersTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new PipesTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new MessageAttachmentsTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new GatewayCredentialsTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new ClientGatewayCredentialsTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new RequestLogTypesTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new RequestLogTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new SessionsTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new PlatformSettingsTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new GatewayIPsTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new ShellsTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new MessageTypesTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new ShellCredentialsTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new MessageStatusesTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new CampaignsTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new GatewaysTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new ClientShellCredentialsTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new MessageDirectionsTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new InterfaceResultsTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new CampaignShellsTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new MessagesTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new CountriesTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new PipeMappingsTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new OutboundGatewayCountriesTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new InboundMessageQueueTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new NetworkOperatorsTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new OutboundMessageQueueTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new CustomersTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new ClientUsersTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new MessageHistoryTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new ClientStatusesTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new OutboundBatchTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new ClientsTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new PipeCampaignKeywordsTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new BillingTypesTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new CampaignIdentifierPoolTable(DataProvider));
            	DataProvider.Schema.Tables.Add(new OutboundBatchMessagesTable(DataProvider));
            }
            #endregion
        }
    }
}